<?php

namespace app\index\controller;

use think\Request;
use think\Controller;

class Futures extends Controller
{
    private $address = '101.132.140.149';
    private $port = 9191;

    public function __construct(Request $request = null)
    {
        parent::__construct($request);
    }

    /**
     * @param $type int 1合约列表 2.分时数据3,历史数据
     * @param $data
     * @return array
     */
    public function index($type, $data)
    {
        set_time_limit(0);
        if (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
            echo "socket_create() failed, reason: " . socket_strerror(socket_last_error()) . "\n";
        }
        socket_connect($socket, $this->address, $this->port);
        if ($type == 1) {
            $list = $this->all_contracts($socket);
        } elseif ($type == 2) {
            $list = $this->time_sharing_index($socket, $data['code']);
        } elseif ($type == 3) {
            $list = $this->history_log($socket, $data['code'], $data['k_type']);
        }
        return $list;
    }

    /**
     * 获取全部合约信息
     * @param $socket
     * @return array
     */
    public function all_contracts($socket)
    {
        socket_write($socket, '000000092');
        $data = socket_read($socket, 98 * 43 + 9);
        socket_close($socket);
//        $head = mb_substr($data, 0, 9);
        $data = mb_substr($data, 9, strlen($data));
        $format = 'a10szCode/a16szName/a8szMarket/flastPrice/ilastVol/fbuyPrice/fsellPrice' . '/SbuyVol/SsellVol/ItradeVol/IlcVol/IlcGapVol/fjsPrice/fopenPrice/fhighPrice/flowPrice' . '/fprejsPrice/ftick/fupperlimit/flowerlimit';
        $length = 10 + 16 + 8 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4;
        $list = $this->bin2string($data, $format, $length);
        return $list;
    }
    //======================================================================================================

    /**
     * 获取分时线信息
     * @param string $socket
     * @param string $code
     * @return array
     */
    public function time_sharing_index($socket, $code = 'GC1812')
    {
        if (!session('list6')) {
            $list_symbol = $this->time_info($socket);
            session('list6', $list_symbol);
            set_time_limit(0);
            if (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
                echo "socket_create() failed, reason: " . socket_strerror(socket_last_error()) . "\n";
            }
            socket_connect($socket, $this->address, $this->port);
        } else {
            $list_symbol = session('list6');
        }
        $symbol = $this->index_symbol($list_symbol, $code);
        $list = $this->time_sharing($socket, $code);
        $data_array = $this->mapping_time($symbol['node'], $list['list']);
        $data = array('list' => $data_array, 'data' => $list['data']);
        return $data;
    }

    /**
     * 映射处理时间
     * @param $nodes
     * @param $mi_list
     * @return array
     */
    private function mapping_time($nodes, $mi_list)
    {
        $data_array = array();
        $price_total = 0;
        $price_num = 1;
        foreach ($nodes as $k => $v) {
            $hour = substr($v, 0, 2);
            $minute = substr($v, 2, 2);
            $num = substr($v, 4, 2);
            if ($num && $mi_list) {
                $mapping_time = array_slice($mi_list, 0, $num);
                foreach ($mapping_time as $key => $value) {
                    $price_total += $value['price'];
                    $value['time'] = $hour . ':' . sprintf("%02d", (floatval($minute) + $key));
                    $value['avPrice'] = round(($price_total / $price_num), 2);
                    array_push($data_array, $value);
                    $price_num++;
                }
                $mi_list = array_slice($mi_list, $num, count($mi_list) - $num);
            }
        }
        return $data_array;
    }

    /**
     * 匹配信息
     * @param $list
     * @param $code
     * @return array
     */
    private function index_symbol($list, $code)
    {
        $data = array();
        foreach ($list as $key => $value) {
            if (strpos($code, $value['pz']) !== false) {
                $data = $value;
            }
        }
        return $data;
    }

    /**
     * 获取品种的分时图时段信息
     * @param $socket
     * @return array
     */
    private function time_info($socket)
    {
        socket_write($socket, '000000096');
        $data = socket_read($socket, 1720);
        socket_close($socket);
//        $head = mb_substr($data, 0, 9);
        $data = mb_substr($data, 12, strlen($data));

        $format = 'A6pz/A8market/itotalsec/itotalpoint/' .
            'lnode1/lnode2/lnode3/lnode4/lnode5/lnode6/lnode7/lnode8/' .
            'lnode9/lnode10/lnode11/lnode12/lnode13/lnode14/lnode15/lnode16/' .
            'lnode17/lnode18/lnode19/lnode20/lnode21/lnode22/lnode23/lnode24/lnode25';
        $length = 6 + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4;
        $list = $this->bin2string($data, $format, $length);
        foreach ($list as $key => $value) {
            $time = array();
            for ($i = 1; $i <= 25; $i++) {
                array_push($time, $value['node' . $i]);
                unset($list[$key]['node' . $i]);
            }
            $list[$key]['node'] = $time;
        }
        foreach ($list as $key => $value) {
            foreach ($value['node'] as $k => $v) {
                $value['node'][$k] = sprintf("%06d", $v);
            }
            $list[$key]['node'] = $value['node'];
        }
        return $list;
    }

    /**
     * 分时数据
     * @param $socket
     * @param $code  string 合约代码
     * @return array
     */
    private function time_sharing($socket, $code)
    {
        $l_ = strlen($code) + 11;
        socket_write($socket, '000000' . $l_ . '5' . $code . ',0');
        $data = socket_read($socket, 100000);
        socket_close($socket);;
        $head = mb_substr($data, 0, 8);
        $data = mb_substr($data, 9, strlen($data));
        $data = mb_substr($data, 12, strlen($data));
        $format = 'spos/ltime/fprice/favPrice/lvol';
        $length = 2 + 4 + 4 + 4 + 4;
        $data2 = mb_substr($data, 0, floatval($head) - 119);
        $list_array = $this->bin2string($data2, $format, $length);
        $format2 = 'a10szCode/a16szName/a8szMarket/flastPrice/ilastVol/fbuyPrice/fsellPrice/SbuyVol/SsellVol/ItradeVol/IlcVol/IlcGapVol/fjsPrice/fopenPrice/fhighPrice/flowPrice/fprejsPrice/ftick/fupperlimit/flowerlimit';
        $length2 = 10 + 16 + 8 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4;
        $data1 = mb_substr($data, -$length2, strlen($data));
        $data_array = unpack("$format2", $data1);
        foreach ($data_array as $key => $value) {            //reference传递是php 5才支持的，如果用php4，得用其他办法
            if (is_string($value)) {
                $value = trim(strtok($value, "\0"));
                $value = iconv('GB2312', 'UTF-8', $value);
            }
            $data_array[$key] = $value;
        }
        return array('list' => $list_array, 'data' => $data_array);
    }
//======================================================================================================

    /**
     * 获取历史数据
     * @param $socket
     * @param string $code 合约信息
     * @param string $type //d--日线 1--分钟线 5--5分钟线 30--30分钟线 60---60分钟线 w--周线 m--月线 y-年线
     * @return mixed
     */
    public function history_log($socket, $code = 'GC1812', $type = '1')
    {
        $length = sprintf("%08d", strlen('00000000A' . $code . ',' . $type . ''));
        $str = $length . 'A' . $code . ',' . $type . '';
        socket_write($socket, $str);
        $data = socket_read($socket, 100000);
        socket_close($socket);
//        $head = mb_substr($data, 0, 9);
        $data = mb_substr($data, 9, strlen($data));
        $data = explode(PHP_EOL, $data);
        foreach ($data as $key => $value) {
            $data[$key] = explode(',', $value);
        }
        return $data;
    }

//======================================================================================================


    /**
     * 获取合约当日K线数据和实时行情数据
     * @param $socket
     * @param $code string  合约代码
     * @param $pos  int K线起始点（从最后一根K线往前算的位置）
     * @param $type int K线类型（0-日线 1-分钟线）
     * @return array
     */
    public function aa_index($socket, $code = 'GC1812', $pos = 12, $type = 1)
    {
        $length = sprintf("%08d", strlen('000000007' . $code . ',' . $pos . ',' . $type . ''));
        $str = $length . '7' . $code . ',' . $pos . ',' . $type . '';
        $list = $this->day_k_line($socket, $str);
        return $list;
    }

    /**
     * 获取合约当日K线数据和实时行情数据
     * @param $socket
     * @param $code
     * @return array
     */
    private function day_k_line($socket, $code)
    {
        socket_write($socket, $code);
        $data = socket_read($socket, 28642);
        socket_close($socket);
        $head = mb_substr($data, 0, 8);
        $data = mb_substr($data, 9, strlen($data));
        $data = mb_substr($data, 13, strlen($data));
        $format = 'spos/ltime/fopen/fhigh/flow/fclose/ivol';
        $length = 2 + 4 + 4 + 4 + 4 + 4 + 4;
        $data2 = mb_substr($data, 0, floatval($head) - 120);
        $list_array = $this->bin2string($data2, $format, $length);
        foreach ($list_array as $key => $value) {
            $list_array[$key]['time'] = date('Y.m.d H:i:s', $value['time']);
        }
        $format2 = 'a10szCode/a16szName/a8szMarket/flastPrice/ilastVol/fbuyPrice/fsellPrice/SbuyVol/SsellVol/ItradeVol/IlcVol/IlcGapVol/fjsPrice/fopenPrice/fhighPrice/flowPrice/fprejsPrice/ftick/fupperlimit/flowerlimit';
        $length2 = 10 + 16 + 8 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4;
        $data1 = mb_substr($data, -$length2, strlen($data));
        $data_array = unpack("$format2", $data1);
        foreach ($data_array as $key => $value) {            //reference传递是php 5才支持的，如果用php4，得用其他办法
            if (is_string($value)) {
                $value = trim(strtok($value, "\0"));
                $value = iconv('GBK', 'UTF-8', $value);
            }
            $data_array[$key] = $value;
        }
        return array('list' => $list_array, 'data' => $data_array);
    }


    /**
     * 数据处理
     * @param $data string 数据
     * @param $format string
     * @param $length int 长度
     * @return array
     */
    private function bin2string($data, $format, $length)
    {
        $list = array();
        for ($i = 0, $c = strlen($data); $i < $c; $i += $length) {
            $bian_bian = unpack("@$i/$format", $data);
            foreach ($bian_bian as &$value) {            //reference传递是php 5才支持的，如果用php4，得用其他办法
                if (is_string($value)) {
                    $value = trim(strtok($value, "\0"));
                    $value = iconv('GB2312', 'UTF-8', $value);
                }
            }
            array_push($list, $bian_bian);
        }
        return $list;
    }
}